package com.example.muchentuner;

import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.SharedElementCallback;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.Log;
import android.view.animation.BounceInterpolator;

import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;

import androidx.core.content.ContextCompat;

import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static com.example.muchentuner.ButtonActivity.*;

import com.airbnb.lottie.LottieAnimationView;

class CanvasPainter {
    private static final double TOLERANCE = 10D;
    private static final int MAX_DEVIATION = 60;
    private static final int NUMBER_OF_MARKS_PER_SIDE = 6;
    private final Context context;

    private Canvas canvas;

    private TextPaint textPaint = new TextPaint(ANTI_ALIAS_FLAG);
    private TextPaint numbersPaint = new TextPaint(ANTI_ALIAS_FLAG);
    private Paint gaugePaint = new Paint(ANTI_ALIAS_FLAG);
    private Paint symbolPaint = new TextPaint(ANTI_ALIAS_FLAG);

    private int FalseBackground;
    private int CorrectBackground;
    private int textColor;

    private PitchDifference pitchDifference;

    public static float gaugeWidth;
    public static float x;
    public static float y;
    private boolean useScientificNotation;
    private int referencePitch;


    private int preWidth;
    private int preHeight;
    private float row;
    private Bitmap bmp;
    //刻度文字 0-100
    private int sideLength=50;//表盘尺寸
    private float sizeScale = 1f;//适配不同分辨率
    private Paint paintTranArc=new Paint();
    private Paint paint1 = new Paint();//刻度
    private Paint paint2 = new Paint();//刻度
    private Paint paintOutSideLine = new Paint();//最外层单线画笔
    private Paint paintLoadArc = new Paint();//加载动起来的圆弧
    private Paint paintDu = new Paint();
    private Paint paintPointer = new Paint();//指针画笔
    private Path pathDu = new Path();


    private CanvasPainter(Context context) {
        this.context = context;
    }

    static CanvasPainter with(Context context) {
        return new CanvasPainter(context);
    }

    CanvasPainter paint(PitchDifference pitchDifference) {
        this.pitchDifference = pitchDifference;

        return this;
    }

    void on(Canvas canvas) {
        SharedPreferences preferences = context.getSharedPreferences(
                PREFS_FILE, Context.MODE_PRIVATE);

        useScientificNotation = preferences.getBoolean(
                USE_SCIENTIFIC_NOTATION, true);

        referencePitch = preferences.getInt(
                REFERENCE_PITCH, 440);

        this.canvas = canvas;//关键所在

        FalseBackground = R.color.false_bg;
        CorrectBackground = R.color.correct_bg;
        textColor = Color.WHITE;


        gaugeWidth = 0.45F * canvas.getWidth();
        x = canvas.getWidth() / 2F;
        y = canvas.getHeight() / 2F;

        textPaint.setColor(textColor);
        int textSize = context.getResources().getDimensionPixelSize(R.dimen.noteTextSize);
        textPaint.setTextSize(textSize);

        setPainter();
        drawArc();

        if (pitchDifference != null) {
            int abs = Math.abs(getNearestDeviation());//
            boolean shouldDraw = abs <= MAX_DEVIATION ||
                    (abs <= MAX_DEVIATION * 2 && !isAutoModeEnabled());
            if (shouldDraw) {
                setBackground(x,y);
                drawRoundRect();
                displayReferencePitch();
                //drawPointer();//要防止pitchDifference为空

                float x = canvas.getWidth() / 2F;
                float y = canvas.getHeight() * 0.87f;

                drawText(x, y, pitchDifference.closest, textPaint);//绘制音符名称
            } else {
                drawListeningIndicator();

            }
        } else {
            drawListeningIndicator();
        }
    }

    private void setPainter(){
        paintTranArc.setStyle(Paint.Style.STROKE);//半透明圆弧，只描边
        paintTranArc.setColor(Color.parseColor("#66ffffff"));
        paintTranArc.setStrokeWidth(80f*sizeScale);
        paintTranArc.setAntiAlias(true);//刻度
        paint1.setStyle(Paint.Style.STROKE);
        paint1.setColor(Color.WHITE);
        paint1.setStrokeWidth(20f*sizeScale);
        paint1.setAntiAlias(true);
        paint2.setStyle(Paint.Style.STROKE);
        paint2.setColor(Color.WHITE);
        paint2.setStrokeWidth(10f*sizeScale);
        paint2.setAntiAlias(true);
        paintOutSideLine.setAntiAlias(true);
        paintOutSideLine.setStrokeWidth(3f);
        paintOutSideLine.setStyle(Paint.Style.STROKE);
        paintOutSideLine.setColor(Color.WHITE);
        paintLoadArc.setAntiAlias(true);
        paintLoadArc.setStrokeWidth(80f*sizeScale);
        paintLoadArc.setStyle(Paint.Style.STROKE);
        paintLoadArc.setColor(Color.WHITE);
        paintDu.setTextAlign(Paint.Align.RIGHT);
        paintDu.setTextSize(48*sizeScale);
        paintDu.setAntiAlias(true);
        paintDu.setColor(Color.WHITE);
        paintPointer.setAntiAlias(true);
        paintPointer.setTextSize(40*sizeScale);
    }


    private void drawArc(){
        float width=(float)(gaugeWidth*0.8);
        float offset=10;
        float rectfp1x=x-width;
        float rectfp1y=y+offset-width;
        float rectfp2x=x+width;
        float rectfp2y=y+offset+width;
        float startAngle=204;
        RectF TranArc_Rec = new RectF(rectfp1x,rectfp1y,rectfp2x,rectfp2y);
        canvas.drawArc(TranArc_Rec,startAngle,133,false,paintTranArc);

        //音准完美的范围
        Paint green_paint=new Paint();
        green_paint.setColor(context.getResources().getColor(R.color.Arc_grey));
        green_paint.setAntiAlias(true);
        green_paint.setStyle(Paint.Style.STROKE);
        green_paint.setStrokeWidth(80f);
        canvas.drawArc(TranArc_Rec,startAngle+55,22,false,green_paint);
        //音准完美的范围

        RectF measure_Rec = new RectF(rectfp1x-51,rectfp1y-51,rectfp2x+51,rectfp2y+51);
        ArrayList<Float> floats = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            floats.add(startAngle);
            startAngle+=22;}
        for (int i = 0; i < floats.size(); i++) {
            canvas.drawArc(measure_Rec, floats.get(i), 1, false, paint1);
        }
        float startAngle2=215;
        RectF measure_Rec2 = new RectF(rectfp1x-47,rectfp1y-47,rectfp2x+47,rectfp2y+47);
        ArrayList<Float> floats2 = new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            floats2.add(startAngle2);
            startAngle2 +=22;}
        for (int i = 0; i < floats2.size(); i++) {
            canvas.drawArc(measure_Rec2, floats2.get(i), 1, false, paint2);
        }

        RectF measureNum_Rec = new RectF(rectfp1x-80,rectfp1y-80,rectfp2x+80,rectfp2y+80);
        float pathstart = 186;
        int[] arr={-60,-40,-20,0,20,40,60};
        for (int i = 0; i < 7; i++) {
            pathDu.reset();
            pathDu.arcTo(measureNum_Rec, pathstart, 22);
            //这也可以啊
            //pathDu.addArc(oval4, pathstart,27);

            int scale = arr[i];
            String scaleStr = String.valueOf(scale);
            if (scale == 0){
                //当刻度是0的时候 有点对不齐
                scaleStr = scaleStr + " ";
            }
            //如果使用 drawText()方法，需要计算文本Text所在坐标
            canvas.drawTextOnPath(scaleStr, pathDu, 0, 0, paintDu);
            pathstart += 22;
        }

    }

    private void displayReferencePitch() {
        float y = canvas.getHeight() * 0.82f;

        TextPaint paint0 = new TextPaint(ANTI_ALIAS_FLAG);
        paint0.setColor(textColor);
        paint0.setTextSize(40f);
        TextPaint paint = new TextPaint(ANTI_ALIAS_FLAG);
        paint.setColor(textColor);
        int size = (int) (textPaint.getTextSize() / 3.5);
        paint.setTextSize(size);

        float offset=0f;
        float y_offset=20;
        canvas.drawText("当前标准音",x - gaugeWidth+50, y+y_offset-100, paint0);
        canvas.drawText(String.format(Locale.ENGLISH, "%d Hz", referencePitch),
                x - gaugeWidth+53 + offset, y+y_offset, paint);
    }

    private void drawRoundRect(){
        Paint p=new Paint();
        p.setStyle(Paint.Style.FILL);//充满
        p.setColor(Color.parseColor("#38ffffff"));
        p.setAntiAlias(true);// 设置画笔的锯齿效果
        float y_offset=90;
        RectF RRectf = new RectF(x-470, y+y_offset+150, x-200, y+y_offset+400);// 设置个新的长方形
        canvas.drawRoundRect(RRectf, 45, 45, p);//第二个参数是x半径，第三个参数是y半径
        RectF RRectf2 = new RectF(x+220, y+y_offset+150, x+470, y+y_offset+400);// 设置个新的长方形
        canvas.drawRoundRect(RRectf2, 45, 45, p);//第二个参数是x半径，第三个参数是y半径
    }

    private void drawListeningIndicator() {
        int resourceId = R.drawable.ic_tuner_mic_unactive;

        if (ListenerFragment.IS_RECORDING) {
            resourceId = R.drawable.ic_tuner_mic_active;
        }

        Drawable drawable = ContextCompat.getDrawable(context, resourceId);

        int x = (int) (canvas.getWidth() / 2F);
        int y = (int) (canvas.getHeight() - canvas.getHeight() / 3F);

        int width = Objects.requireNonNull(drawable).getIntrinsicWidth() * 2;
        int height = drawable.getIntrinsicHeight() * 2;//得到drawable的真实高度
        drawable.setBounds(
                x - width / 2, y,
                x + width / 2,
                y + height);


        drawable.draw(canvas);
    }

    private void drawText(float x, float y, Note note, Paint textPaint) {
        String noteText = getNote(note.getName());
        float offset = textPaint.measureText(noteText) / 2F;

        String sign = note.getSign();
        String octave = String.valueOf(getOctave(note.getOctave()));

        TextPaint paint = new TextPaint(ANTI_ALIAS_FLAG);
        paint.setColor(textColor);
        int textSize = (int) (textPaint.getTextSize() / 2);
        paint.setTextSize(textSize);

        float factor = 0.75f;
        if (useScientificNotation) {
            factor = 1.5f;
        }
        float offset111=-40;
        float y_offset=-40;

        canvas.drawText(sign, x + offset * 1.25f+offset111, y+y_offset - offset * factor, paint);
        canvas.drawText(octave, x + offset * 1.25f+offset111, y+y_offset + offset * 0.5f, paint);

        canvas.drawText(noteText, x - offset+offset111, y+y_offset, textPaint);
    }

    private int getOctave(int octave) {
        if (useScientificNotation) {
            return octave;
        }

        /*
            The octave number in the (French notation) of Solfège is one less than the
            corresponding octave number in the scientific pitch notation.
            There is also no octave with the number zero
            (see https://fr.wikipedia.org/wiki/Octave_(musique)#Solf%C3%A8ge).
         */
        if (octave <= 1) {
            return octave - 2;
        }

        return octave - 1;
    }

    private String getNote(NoteName name) {
        if (useScientificNotation) {//科学计数法
            return name.getScientific();
        }

        return name.getSol();
    }

    private void setBackground(float x,float y) {
        int color = FalseBackground;
        if (Math.abs(getNearestDeviation()) <= TOLERANCE) { //tolerance就是音是准的范围标准10
            color = CorrectBackground;
        }
        Paint paint=new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setColor(context.getResources().getColor(color));
        RectF rectF=new RectF(0,y+120,2*x,y+650);
        canvas.drawRect(rectF,paint);
        //canvas.drawColor(context.getResources().getColor(color));//设置背景色
    }

    private int getNearestDeviation() {
        float deviation = (float) pitchDifference.deviation;
        int rounded = Math.round(deviation);
        //return Math.round(rounded / 10f) * 10;
        return rounded;
    }
}

